perm filename ALGOL.SAI[PUB,TES] blob
sn#195729 filedate 1976-01-28 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00011 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 BEGOF("ALGOL")
C00004 00003 PUBLIC SIMPLE PROCEDURE ALGOL! $"#
C00005 00004 PUBLIC RECURSIVE BOOLEAN PROCEDURE CHUNK(BOOLEAN VALID) $"#
C00006 00005 PUBLIC RECURSIVE PROCEDURE DCONDITIONAL $"#
C00007 00006 PUBLIC RECURSIVE STRING PROCEDURE E(STRING DEFAULT, STOPWORD) $"#
C00024 00007 PRIVATE BOOLEAN SIMPLE PROCEDURE EMPTYCHUNK $"#
C00025 00008 PUBLIC SIMPLE PROCEDURE MANUSCRIPT $"#
C00026 00009 PRIVATE BOOLEAN SIMPLE PROCEDURE NONSENSE(BOOLEAN VALID) $"#
C00027 00010 PUBLIC RECURSIVE BOOLEAN PROCEDURE STATEMENT $"#
C00028 00011 FINISHED
C00029 ENDMK
C⊗;
BEGOF("ALGOL")
COMMENT
The ALGOL (SAIL) subset of PUB -- statements, conditionals, and
expressions.
The statement parser is recursive descent. Its top-level production
is MANUSCRIPT. A manuscript is a sequence of CHUNKs, including
ASSIGNMENTs, LABELDEFinitions, COMMANDs, PROCedureSTATEMENTs, and
TEXTLINEs.
The expression parser is iterative descent. Its top-level production
is E. An E is a conditional expression, an assignment expression, or
a simple expression.
;
PROCEDURES
PUBLIC SIMPLE PROCEDURE ALGOL! ;$"#
BEGIN "ALGOL!"
ON ← TRUE ; COMMENT TO EXECUTE PARSED CODE ;
LIT!ENTITY ← LIT!TRAIL ← NULL ;
EMPTYTHIS ; EMPTYTHAT ;
END "ALGOL!" ;
PUBLIC RECURSIVE BOOLEAN PROCEDURE CHUNK(BOOLEAN VALID) ;$"#
BEGIN
IF PAGEMARKS > PAGEWAS THEN
BEGIN comment, might be AT PAGEMARK response ;
FOR PAGEWAS ← PAGEWAS + 1 THRU PAGEMARKS DO IF SIGNALD[FF] THEN RESPOND(SIGNALD[FF]) ;
PAGEWAS ← PAGEMARKS ;
END ;
RETURN(THISISID AND (ASSIGNMENT OR LABELDEF OR COMMAND OR PROCSTATEMENT)
OR TEXTLINE OR EMPTYCHUNK OR NONSENSE(VALID)) ;
TES ADDED PROCSTATEMENT 8/20/74 ;
END "CHUNK" ;
PUBLIC RECURSIVE PROCEDURE DCONDITIONAL ;$"#
BEGIN
BOOLEAN WASON ;
WASON ← ON ; PASS ; ON ← TRUESTR(E(NULL,"THEN")) AND WASON ;
IF ITS(THEN) THEN PASS ELSE WARN("=","Missed THEN in conditional statement") ;
IF STATEMENT THEN BEGIN ON←TRUE; RETURN END; TES 8/14/74 DONE FROM REPEAT ;
IF ITS(ELSE) THEN BEGIN ON←WASON AND NOT ON; PASS ; IF STATEMENT THEN BEGIN ON←TRUE; RETURN END END ;
ON ← WASON ;
END "DCONDITIONAL" ;
PUBLIC RECURSIVE STRING PROCEDURE E(STRING DEFAULT, STOPWORD) ;$"#
COMMENT Scan a SAIL-Like <Expression>. First check trivial case. ;
IF ITS(IF) THEN
BEGIN "CONDITIONAL EXPRESSION"
STRING BOOLX, THENX, ELSEX ; BOOLEAN WASON ;
WASON ← ON ; PASS ;
BOOLX ← E(NULL, "THEN") ; ON ← WASON AND TRUESTR(BOOLX) ;
IF ITS(THEN) THEN PASS ELSE WARN("=","Missed THEN in conditional expression "&THISWD) ;
THENX ← E(NULL, "ELSE") ;
IF ITS(ELSE) THEN
BEGIN
ON ← WASON AND FALSTR(BOOLX) ; PASS ;
ELSEX ← E(NULL, STOPWORD) ;
END
ELSE ELSEX ← NULL ;
ON ← WASON ;
RETURN(IF TRUESTR(BOOLX) THEN THENX ELSE ELSEX) ;
END "CONDITIONAL EXPRESSION"
ELSE IF THISTYPE = -TERQ OR THISTYPE = CMDTYPE OR ITSV(STOPWORD) THEN
RETURN(DEFAULT) comment omitted expression ;
ELSE IF THISTYPE GEQ -1 AND (THATTYPE = -TERQ OR THATTYPE=CMDTYPE OR NEXTSV(STOPWORD)) THEN
RETURN(SPASS(<IF THISISCON THEN THISWD[2 TO ∞] ELSE VEVAL>))
ELSE IF THISISID AND NEXTSCH(←) THEN comment, Assignment Expression ;
RETURN(VASSIGN(SYMB, THISTYPE, IX, E(IPASS(PASS), STOPWORD)))
ELSE
BEGIN "SIMPLE EXPRESSION"
STRING ANY, comment, result of A OR B OR ...: has value of first TRUE operand;
ALL, comment, result of A AND B AND ...: has value of first FALSE operand;
COMPARE, comment, result of A<B LEQ ...: TRUE if all relations are TRUE;
LEFT, comment, preceding right comparator, saved for another comparison;
BOUNDARY, comment, result of A MAX B MIN... ;
PRODUCT, comment, result of * / MOD & ;
PRIMARY ; comment, <const>|<var>|( <expr> )|<unary><primary>|<primary><substr spec> ;
INTEGER OROP, comment, =0 signals OR waiting for right operand ;
ANDOP, NOTOP, comment, =0 signals AND or NOT operator waiting ;
RELOP, ODDOP, BOUNDOP, ADDOP, MULOP, comment, GEQ 0 signals operator waiting ;
UNARYOP, comment, GEQ 0 signals unary operators waiting ;
U, comment, last of a series of unary operators ;
SS1, comment, starting byte number in substring spec ;
SAVEINF, comment, saved outside value of ∞ ;
SYMPTR, comment, symbol table number of identifier ;
IDTYPE, comment, type field in its NUMBER entry ;
ICOMPARE, ILEFT, IBOUNDARY, ISUM, IPRODUCT, IPRIMARY ; comment, CVD(corresponding string);
BOOLEAN WASONA, WASONO ; comment value of ON before a series of conjuncts or disjuncts ;
DEFINE TRYFAMILY(FAM) = [IF THISTYPE=-FAM THEN IPASS(IX)];
COMMENT Multiple Unary operators ( + , - , ABS , LENGTH , XLENGTH , and ↑ ) are combined
into a single operator by inventing new operators such as
"-ABS" and "ABS LENGTH" ;
DEFINE P = [0], comment, +X ; M = [1], comment, -X ; A = [2], comment, ABS X ;
MA = [3], comment, -ABS X ; C = [4], comment, ↑X ;
L = [5], comment, LENGTH(X) ; ML = [6], comment -LENGTH(X) ;
AL = [7], comment, ABS LENGTH(X) ; MAL = [8], comment, -ABS LENGTH(X) ;
Z = [9], comment, XLENGTH(X) ; MZ = [10], comment -XLENGTH(X) ;
AZ = [11], comment, ABS XLENGTH(X) ; MAZ = [12]; comment, -ABS XLENGTH(X) ; TES 8/14/74 ;
PRELOAD!WITH comment RIGHT OPERATOR
---------------------------------
LEFT OPERATOR + - ABS ↑ LENGTH XLENGTH
------------- --- --- --- --- -------- ---------
none; P, M, A, C, L, Z,
comment P ; P, M, A, P, L, Z,
comment M ; M, P, MA, M, ML, MZ,
comment A ; A, A, A, A, AL, AZ,
comment MA ; MA, MA, MA, MA, MAL, MAZ,
comment C ; P, M, A, C, L, Z ;
OWN INTEGER ARRAY COMBINE[-1:4,0:5] ;
COMMENT This is a top-down expression parser, but iteration is used
instead of recursion for rapidity ;
OROP ← ANDOP ← NOTOP ← RELOP ← BOUNDOP ← ADDOP ← MULOP ← -1 ;
WASONO ← ON ;
DO BEGIN "DISJUNCTS" COMMENT Operands of OR ;
WASONA ← ON ;
DO BEGIN "CONJUNCTS" COMMENT Operands of AND ;
WHILE THISTYPE = -NOTQ DO BEGIN NOTOP ← -1 - NOTOP ; PASS END ;
ICOMPARE ← TRUE ;
DO BEGIN "COMPARATORS" COMMENT Operands of < = etc. ;
ODDOP ← TRYFAMILY(ODDQ) ELSE -1 ;
DO BEGIN "BOUNDS" COMMENT Operands of MAX and MIN ;
DO BEGIN "TERMS" COMMENT Operands of + - ≡ ⊗ ;
DO BEGIN "FACTORS" COMMENT Operands of * / MOD & ;
UNARYOP ← -1 ; COMMENT check for Unary Operators ;
WHILE UNARYOP LEQ 3 COMMENT no, P, M, A, or MA left operator ;
AND 0 LEQ (U ← TRYFAMILY(ADDQ) ELSE -1) COMMENT some right operator ;
DO UNARYOP ← COMBINE[UNARYOP, U] ;
comment PRIMARY ;
IF THISISCON THEN BEGIN PRIMARY ← THISWD[2 TO ∞] ; PASS END
ELSE IF THISISID THEN
IF ITSV(STOPWORD) THEN
BEGIN
PRIMARY ← DEFAULT ;
WARN("=","Ill-Formed Expression" & THISWD) ;
END
ELSE IF PROCSTATEMENT THEN PRIMARY ← PROCVALUE
ELSE IF NEXTSCH(<(>) THEN
BEGIN "FUNCALL" TES 8/19/74 ;
IF ITS(DECLARATION) THEN
BEGIN
DCLR!ID ← TRUE ; TES 1/8/75 ;
PASS ; PASS ;
PRIMARY ← CVS(THISTYPE) ;
DCLR!ID ← FALSE ; TES 1/8/75 ;
PASS ;
END
ELSE IF ITS(OCTAL) THEN
BEGIN
STRING T ;
PRIMARY ← NULL ; PASS ; PASS ; T ← E(NULL,NULL) ;
WHILE T DO PRIMARY ← PRIMARY & "'" & CVOS(LOP(T)) ;
END
ELSE IF ITS(BEWARE) THEN
BEGIN TES 8/21/74 INVERSE OCTAL ;
RKJ: 6-Feb-75 ALSO DECIMAL ;
STRING T ; INTEGER BRC ;
PRIMARY ← NULL ; PASS ; PASS ; T ← E(NULL,NULL) ;
SETBREAK(LOCAL!TABLE,"'#",NULL,"IS") ;
DO BEGIN
SCAN(T, LOCAL!TABLE, BRC) ;
IF BRC = "'"
THEN PRIMARY ← PRIMARY & CVO(T)
ELSE IF BRC = "#" THEN PRIMARY ← PRIMARY & CVD(T) ;
END UNTIL NOT BRC ;
END
ELSE IF ITS(SCAN) THEN
BEGIN "SCANCALL"
BOOLEAN ISBRC ;
STRING STR, STOPPERS, IGNORES, OPTIONS ;
INTEGER SYMWAS, IXWAS, TYPEWAS, BRC ;
STOPPERS←IGNORES←OPTIONS←NULL ;
ISBRC ← FALSE ; PASS ; PASS ;
IF THISISID AND NEXTSCH(<,>) THEN
BEGIN COMMENT VARIABLE TO LOP ;
SYMWAS←SYMBOL; IXWAS←IX; TYPEWAS←THISTYPE;
STR ← VEVAL ; PASS ;
END
ELSE BEGIN COMMENT EXPRESSION ;
IXWAS ← -1 ;
STR ← E(NULL, NULL) ;
END ;
IF ITSCH(<,>) THEN
BEGIN COMMENT STOPPERS ;
PASS ; STOPPERS←E(NULL, NULL) ;
IF ITSCH(<,>) THEN
BEGIN COMMENT IGNORES ;
PASS ; IGNORES ← E(NULL,NULL) ;
IF ITSCH(<,>) THEN
BEGIN COMMENT OPTIONS ;
PASS ; OPTIONS ← E(NULL,NULL) ;
IF ITSCH(<,>) THEN
BEGIN COMMENT BRC VARIABLE ;
PASS ;
IF THISISID AND NEXTSCH(<)>) THEN
ISBRC←TRUE
ELSE WARN(NULL, "SCAN's BRC must be variable name") ;
END ;
END ;
END ;
END ;
SETBREAK(LOCAL!TABLE, STOPPERS, IGNORES,
IF FULSTR(OPTIONS) THEN OPTIONS ELSE "IR") ;
PRIMARY ← SCAN(STR, LOCAL!TABLE, BRC) ;
BREAKSET(LOCAL!TABLE, NULL, "O") ; TES 10/1/74 ;
IF ISBRC THEN
BEGIN
VASSIGN(SYMBOL, THISTYPE, IX, IF BRC=0 THEN NULL ELSE BRC) ;
PASS ;
END ;
IF IXWAS NEQ -1 THEN VASSIGN(SYMWAS, TYPEWAS, IXWAS, STR) ;
END "SCANCALL"
ELSE BEGIN
WARN(NULL,"Unknown Function " & THISWD) ;
PASS ; PASS ; PRIMARY ← DEFAULT ;
WHILE NOT ITSCH(<)>) DO
IF ITSCH(<,>) THEN PASS
ELSE E(NULL,NULL) ;
END ;
IF ITSCH(<)>) THEN PASS
ELSE WARN(NULL, <"Missing ) after function call">) ;
END "FUNCALL"
ELSE BEGIN PRIMARY ← VEVAL ; PASS END
ELSE IF ITSCH(<(>) THEN
BEGIN "( <EXPR> )"
PASS ; PRIMARY ← E(DEFAULT, 0) ;
IF ITSCH(<)>) THEN PASS ELSE WARN("=",<"Missed )">) ;
END "( <EXPR> )"
ELSE BEGIN WARN("=","Ill-Formed expression" & THISWD) ; PRIMARY ← DEFAULT END ;
WHILE THISTYPE=-BROKQ DO COMMENT Substring Specifications ;
BEGIN "SUBSPEC"
PASS ; SAVEINF ← INF ; INF ← LENGTH(PRIMARY) ;
SS1 ← CVD(E("1", IF NEXTS(TO) THEN "TO" ELSE "FOR")) ;
IF ITS(TO) THEN BEGIN PASS ; PRIMARY←PRIMARY[SS1 TO CVD(E("0",0))] END
ELSE IF ITS(FOR) THEN BEGIN PASS ; PRIMARY←PRIMARY[SS1 FOR CVD(E("1",0))] END
ELSE PRIMARY ← PRIMARY[SS1 FOR 1] ;
SAIL!SKIP! ← !SKIP! ;
IF ITSCH(<]>) THEN PASS ELSE WARN("=",<"Missed ] in substring spec " & THISWD>) ;
INF ← SAVEINF ;
END "SUBSPEC" ;
IF UNARYOP LEQ 3 THEN COMMENT both int & str versions maintained when needed ;
IPRIMARY ← IF PRIMARY="'" THEN CVO(PRIMARY[2 TO ∞]) TES 8/19/74 ;
ELSE CVD(PRIMARY) ;
IF UNARYOP GEQ 0 THEN IF UNARYOP=C THEN IPRIMARY←CVD(PRIMARY←CAPITALIZE(PRIMARY))
ELSE PRIMARY ← CVS(IPRIMARY ← CASE UNARYOP OF (IPRIMARY, -IPRIMARY,
ABS IPRIMARY, -ABS IPRIMARY, 0, LENGTH(PRIMARY), -LENGTH(PRIMARY),
ABS LENGTH(PRIMARY), -ABS LENGTH(PRIMARY),
XLENGTH(PRIMARY), -XLENGTH(PRIMARY),
ABS XLENGTH(PRIMARY), -ABS XLENGTH(PRIMARY) ) ) ; TES 8/14/74;
IF MULOP<0 THEN BEGIN PRODUCT ← PRIMARY ; IPRODUCT ← IPRIMARY END
ELSE IF MULOP = 3 THEN IPRODUCT ← CVD(PRODUCT ← PRODUCT & PRIMARY)
ELSE PRODUCT ← CVS(IPRODUCT ← IF IPRIMARY=0 OR NOT ON THEN 0 ELSE CASE MULOP OF
(IPRODUCT*IPRIMARY, IPRODUCT DIV IPRIMARY, IPRODUCT MOD IPRIMARY) ) ;
MULOP ← TRYFAMILY(MULQ) ELSE -1 ;
END "FACTORS" UNTIL MULOP < 0 ;
ISUM ← CASE ADDOP+2 OF (IPRODUCT, IPRODUCT, ISUM + IPRODUCT,
ISUM - IPRODUCT, ISUM ≡ IPRODUCT, ISUM ⊗ IPRODUCT) ;
ADDOP ← TRYFAMILY(ADDQ) ELSE IF ADDOP<0 THEN -1 ELSE -2 ;
END "TERMS" UNTIL ADDOP < 0 ;
IBOUNDARY ← CASE BOUNDOP+2 OF (ISUM, ISUM, IBOUNDARY MAX ISUM, IBOUNDARY MIN ISUM) ;
BOUNDOP ← TRYFAMILY(BOUNDQ) ELSE IF ADDOP=-1 AND BOUNDOP<0 THEN -1 ELSE -2 ;
END "BOUNDS" UNTIL BOUNDOP < 0 ;
BOUNDARY ← IF BOUNDOP = -1 THEN PRODUCT COMMENT, hasn't changed since then; ELSE CVS(IBOUNDARY) ;
IF ODDOP GEQ 0 THEN BOUNDARY←CVS(IBOUNDARY←(IBOUNDARY MOD 2)=ODDOP);
IF ICOMPARE THEN CASE RELOP+2 OF BEGIN comment SAIL Bug precludes case expression with relationals;
BEGIN END ; BEGIN END ; ICOMPARE←ILEFT<IBOUNDARY; ICOMPARE←ILEFT>IBOUNDARY; ICOMPARE ←
EQU(LEFT,BOUNDARY); ICOMPARE←ILEFT LEQ IBOUNDARY; ICOMPARE←ILEFT GEQ IBOUNDARY;
ICOMPARE← NOT EQU(LEFT,BOUNDARY) END ;
RELOP ← TRYFAMILY(RELQ) ELSE IF RELOP < 0 THEN -1 ELSE -2 ;
LEFT ← BOUNDARY ; ILEFT ← IBOUNDARY ;
END "COMPARATORS" UNTIL RELOP < 0 ;
COMPARE ← IF RELOP=-1 THEN BOUNDARY ELSE CVS(ICOMPARE) ;
IF NOTOP = 0 THEN COMPARE ← IF TRUESTR(COMPARE) THEN "0" ELSE "-1" ;
NOTOP ← -1 ;
IF ANDOP < 0 OR TRUESTR(ALL) THEN IF FALSTR(ALL ← COMPARE) THEN ON ← FALSE ;
ANDOP ← TRYFAMILY(ANDQ) ELSE -1 ; ALL ← ALL ; comment SAIL bug -- force it to store;
END "CONJUNCTS" UNTIL ANDOP < 0 ;
ON ← WASONA ;
IF OROP < 0 OR FALSTR(ANY) THEN IF TRUESTR(ANY ← ALL) THEN ON ← FALSE ;
OROP ← TRYFAMILY(ORQ) ELSE -1 ; ANY ← ANY ; comment SAIL bug -- force it to store ;
END "DISJUNCTS" UNTIL OROP < 0 ;
ON ← WASONO ;
RETURN(DUMMYSTR ← ANY) ; comment, DUMMYSTR due to SAIL RECURSIVE STRING PROCEDURE bug (see DCS);
END "SIMPLE EXPRESSION" ;
PRIVATE BOOLEAN SIMPLE PROCEDURE EMPTYCHUNK ;$"#
RETURN(IF ITSCH(;) THEN IPASS(TRUE) ELSE FALSE) ;
PUBLIC SIMPLE PROCEDURE MANUSCRIPT ;$"#
BEGIN
BOOLEAN VALID ;
PASS ; COMMENT 9/9/74 TES ;
VALID ← TRUE ;
DO VALID ← CHUNK(VALID) UNTIL LAST < 1 ;
IF NOT NEXTS(7!MANUSCRIPT) THEN WARN("=","Brackets don't pair up!!!!!!!!!") ;
FINPORTION ; IF BLNMS=0 THEN ENDBEGIN ELSE IF BLNMS>0 THEN
WARN("=",CVS(BLNMS) & " Extra BEGINs and STARTs") ;
END "MANUSCRIPT" ;
PRIVATE BOOLEAN SIMPLE PROCEDURE NONSENSE(BOOLEAN VALID) ;$"#
BEGIN
IF VALID THEN WARN("=","Can't make sense out of: "&SOMEINPUT) ;
PASS ; RETURN(FALSE) ;
END "NONSENSE" ;
PUBLIC RECURSIVE BOOLEAN PROCEDURE STATEMENT ;$"#
BEGIN "STATEMENT"
INTEGER LVL, RLVL ; BOOLEAN VALID ;
LVL ← BLNMS ; RLVL ← DEEPREPEATS ; TES 8/14/74 ;
DO VALID ← CHUNK(VALID) UNTIL BLNMS LEQ LVL ;
RETURN(RLVL > DEEPREPEATS) ; TES 8/14/74 ;
END "STATEMENT" ;
FINISHED
ENDOF("ALGOL")